<script lang="jsx" setup>
import { defineAsyncComponent, inject, ref, watch } from 'vue';
import { SearchOutlined } from '@ant-design/icons-vue';
import SortFieldSelector from './components/sort-field-selector.vue';
import SortModeSelector from './components/sort-mode-selector.vue';
import BaseTreeFilter from '@/components/base-tree-filter.vue';
import router from '@/router/index.js';
import { toFormData, REQU, useResp, SignInInfoInvalidCondPair } from '@/net/requ.js';
import { assignStatusOptions, taskOptions } from '@/util/const.js';
import * as storage from '@/util/storage.js';
import { OptionsFlatted, asgmntEq, asgmntGte, optsToDic } from '@/util/index.js';
import { Modal, Tag, message } from 'ant-design-vue';
const LabelStats = defineAsyncComponent(() => import('./label-stats.vue'));
const labelStatsProps = ref({ visible: false });

const auth = inject('auth');

const userInfo = storage.readAsObj('userInfo');

/** 进入任务按钮，未分配仅创建人可见 */
const assignVisibility = (() => {
  return userInfo
    ? R.anyPass([
        asgmntGte('已分配'),
        R.allPass([ asgmntEq('未分配'), R.propEq(userInfo.userId, 'createByUserId') ])
      ])
    : R.F;
})();

function StatusTag(props) {
  const statusDic = optsToDic(assignStatusOptions);
  const StatusTxt = R.compose( R.prop(R.__, statusDic), R.prop('assignmentStatus') );
  const Color = R.compose(
    R.cond([
      [asgmntEq('已完成'), R.always('green')],
      [asgmntEq('已分配'), R.always('blue')],
      [R.T,             R.always('default')],
    ]),
  );
  return <Tag color={Color(props.task)}>{StatusTxt(props.task)}</Tag>;
}

const TypeIconSrc = type => new URL(`../../assets/all-task/type${ type.toString()[0] }.webp`, import.meta.url).href;

const TaskPath = R.cond([
  [asgmntEq('未分配'), R.compose( R.concat(`/task-assign-`), R.toString, R.prop('type') )],
  [R.T,             R.always('/task-detail')],
]);

const flatted = OptionsFlatted(taskOptions);
const TaskTypeTxt = R.propOr('--', R.__, optsToDic(flatted));

const selectedKeys = ref([]);
const loading = ref(false);
const list = ref([]);

const orderFieldList = ref([
  { value: 'update_by_time', label: '最新' },
  { value: 'created_by_time', label: '最早' },
  { value: 'task_name', label: '名称' }
]);

const params = ref({
  group: '',
  type: '',
  assignmentStatus: '',
  date: null,
  get startTime() {
    return this.date?.[0]?.format('YYYY-MM-DD') ?? '';
  },
  get endTime() {
    return this.date?.[1]?.format('YYYY-MM-DD') ?? '';
  },
  start: 1,
  limit: 10,
  queryString: '',
  orderField: orderFieldList.value[0].value,
  orderType: 'DESC',
});

watch(
  () => params.value.queryString,
  () => (params.value.start = 1)
);

watch(params, getTasks, { deep: true });

const pagination = ref({
  total: 0,
  get current() {
    return params.value.start;
  },
  get pageSize() {
    return params.value.limit;
  },
  onChange: page => {
    params.value.start = page;
    localStorage.setItem('all-task', JSON.stringify({ params: { start: page } }));
  },
});

function getTasks() {
  loading.value = true;
  REQU(`/api/task/list?${ new URLSearchParams(params.value) }`)
  .then(useResp({
    succ: result => {
      list.value = result.data.list;
      pagination.value.total = result.data.total;
    },
    fail: R.cond([SignInInfoInvalidCondPair()]),
  }))
  .finally(() => loading.value = false);
}

function delTaskConfirm(ids) {
  return Modal.confirm({
    centered: true,
    title: '删除任务',
    content: '确定删除此任务？',
    onOk: () => delTask(ids)
      .then(() => {
        message.success('删除成功');
        getTasks();
      })
      .catch(() => message.warn('删除失败'))
  });
}

function delTask(ids) {
  return REQU('/api/task/delete', {
    method: 'POST',
    body: toFormData({
      ids: ids.join(','),
      logicalDelete: true
    })
  })
}

function main() {
  if (!userInfo) {
    message.error('请重新登录');
    router.replace('/sign-in');
    return;
  }

  params.value.start = R.pathOr(1, ['params', 'start'], storage.readAsObj('all-task'));
  getTasks();
}

main();

function handleDeselect() {
  selectedKeys.value = [];
  params.value.type = '';
}

function handleSelect({ key }) {
  selectedKeys.value = [key];
  params.value.type = key;
}

function onCalendarChange(...args) {
  console.log(args);
}
</script>

<template>
  <div class="all-task">
    <base-tree-filter title="标注任务" searchable :onChange="e => null">
      <a-menu
        v-model:selectedKeys="selectedKeys"
        mode="inline"
        multiple
        :inlineIndent="10"
        @deselect="handleDeselect"
        @select="handleSelect"
      >
        <template v-for="(type, i) in taskOptions" :key="i">
          <a-sub-menu>
            <template #title>{{ type.label }}</template>
            <template v-for="subType in type.options" :key="subType.value">
              <a-menu-item>{{ subType.label }}</a-menu-item>
            </template>
          </a-sub-menu>
        </template>
      </a-menu>
    </base-tree-filter>

    <header>
      <div class="btns">
        <!-- @click="() => router.push('/label-stats')" -->
        <a-button
          type="primary"
          @click="() => (labelStatsProps.visible = true)">
          标签统计
        </a-button>

        <a-button
          v-if="auth"
          v-exist:task="'添加'"
          class="green"
          type="primary"
          @click="() => router.push('/task-edit')">
          + 新建任务
        </a-button>
      </div>
      <div class="filter">
        <a-input
          v-model:value="params.queryString"
          placeholder="输入关键字搜索任务"
          allow-clear
          style="width: 200px; border-radius: 18px;">
          <template #prefix>
            <search-outlined style="color: rgb(181,181,181);" />
          </template>
        </a-input>

        <div>
          <span>创建日期：</span>
          <a-range-picker
            v-model:value="params.date"
            format="YYYY-MM-DD"
            :placeholder="['开始日期', '结束日期']"
            @calendarChange="onCalendarChange"
          >
          </a-range-picker>
        </div>

        <div class="assign">
          <span>分配状态：</span>
          <a-select
            v-model:value="params.assignmentStatus"
            :options="[{ value: '', label: '全部' }].concat(assignStatusOptions)"
            style="width: 100px;"
          >
          </a-select>
        </div>

        <sort-mode-selector v-model:value="params.orderType"></sort-mode-selector>

        <sort-field-selector
          :list="orderFieldList"
          v-model:value="params.orderField"
        >
        </sort-field-selector>
      </div>
    </header>
  
    <a-spin :spinning="loading">
      <ul class="list">
        <template v-for="task in list" :key="task.id">
          <li>
            <img class="type-icon" :src="TypeIconSrc(task.type)" alt="">

            <main>
              <h4 class="ellipsis" :title="task.taskName">
                {{ task.taskName }}
                <status-tag :task="task"></status-tag>
              </h4>
  
              <div class="action">
                <span>创建于 {{ task.createdByTime }}</span>
                <span>所属类别：{{ TaskTypeTxt(task.type) }}</span>
              </div>
            </main>

            <div class="extra">
              <a-button
                v-if="assignVisibility(task)"
                v-exist:task="'进入任务'"
                type="primary"
                ghost
                @click="() => router.push({ path: TaskPath(task), query: { id: task.id } })">
                进入任务
              </a-button>
              <a-button
                v-exist:task="'编辑'"
                type="link"
                @click="() => router.push({ path: '/task-edit', query: { id: task.id } })">
                编辑
              </a-button>
              <!-- <a-button type="link" @click="() => delTaskConfirm([task.id])" style="color: var(--default-color);">删除</a-button> -->
            </div>
          </li>
        </template>
      </ul>
      <a-pagination
        :current="pagination.current"
        :pageSize="pagination.pageSize"
        :total="pagination.total"
        show-less-items
        show-size-changer
        @change="pagination.onChange"
        @showSizeChange="(current, pageSize) => params.limit = pageSize"
      >
      </a-pagination>
    </a-spin>
  </div>

  <label-stats v-model:visible="labelStatsProps.visible" />
</template>

<style>
.all-task {
  display: grid;
  gap: 16px;
  grid-template-areas:
    'aside header'
    'aside .';
  grid-template-rows: auto 1fr;
  grid-template-columns: 240px 1fr;
  padding: 24px;
  height: 100%;
  min-height: 800px;
}

.all-task .tree-filter { grid-area: aside; }

.all-task > header {
  grid-area: header;
  gap: 1em;
}

.all-task > header > .btns {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
}

.all-task > header > .filter {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.all-task > header > .btns .ant-btn-primary.green {
  border-color: rgb(0,170,0);
  background: rgb(0,170,0);
  color: #fff;
}

.all-task > header > .btns .ant-btn-primary.green:hover {
  border-color: rgb(0,190,0);
  background-color: rgb(0,190,0);
  color: #fff;
}

.all-task .list { overflow: auto; }
.all-task .list > li {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  padding: 30px 24px;
  background: #fff;
  border-radius: 6px;
  transition: box-shadow .5s;
}
.all-task .list > li:hover { box-shadow: 0 2px 20px 0 rgba(31,35,41,.18); }
.all-task .list > li:not(:last-child) { margin-bottom: 1em; }

.all-task .list main {
  flex: 1;
  width: 0;
}

.all-task .list h4 {
  margin-bottom: 20px;
  font-size: 16px;
  font-weight: bold;
}

.all-task .list h4 .ant-tag {
  margin-left: .5em;
  border-radius: .75em;
}

.all-task .list .action {
  display: flex;
  color: rgba(31,35,41,.6);
}

.all-task .list .action > span::after {
  content: '|';
  padding-left: 12px;
  padding-right: 12px;
  color: rgba(31,35,41,.1);
}

.all-task .list .extra {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  width: 88px;
}

.all-task .list .extra .ant-btn-link {
  width: 40px;
  padding-left: 0;
  padding-right: 0;
}

.all-task .ant-pagination {
  display: flex;
  justify-content: center;
}
</style>
